import applicationApi from '@/api/application';
import { asyncAppAuthentication } from '@/api/common';
import logApi from '@/api/log';
import { ChatManagement } from '@/api/type/application';
import AnswerContent from '@/components/ai-chat/component/answer-content';
import ChatInputOperate from '@/components/ai-chat/component/chat-input-operate';
import PrologueContent from '@/components/ai-chat/component/prologue-content';
import QuestionContent from '@/components/ai-chat/component/question-content';
import { isWorkFlow } from '@/utils/application';
import { randomId } from '@/utils/utils';
import { debounce } from 'lodash';
import React, {
    forwardRef,
    useCallback,
    useEffect,
    useImperativeHandle,
    useMemo,
    useRef,
    useState
} from 'react';



const AiChat = forwardRef((props, ref) => {
    const aiChatRef = useRef(null);
    const scrollDiv = useRef(null);
    const dialogScrollbar = useRef(null);
    const [loading, setLoading] = useState(false);
    const [inputValue, setInputValue] = useState('');
    const [chartOpenId, setChartOpenId] = useState('');
    const [chat, setChat] = useState({});
    const [chatList, setChatList] = useState(props.record || []);
    const [form_data, setForm_data] = useState({});
    const [api_form_data, setApi_form_data] = useState({});
    const route = window.location;
    const {
        params: { accessToken, id },
        query: { mode }
    } = { params: {}, query: {} }; // 假设这里可以从 route 中获取 accessToken、id 和 mode

    const isMobile = useMemo(() => {
        return window.common?.device || mode === 'embed';
    }, [mode]);

    useEffect(() => {
        console.log('props', props);
        if (props.chatId && props.chatId!== 'new') {
            setChartOpenId(props.chatId);
        } else {
            setChartOpenId('');
        }
    }, [props.chatId]);

    useEffect(() => {
        setChartOpenId('');
    }, [props.applicationDetails]);

    useEffect(() => {
        setChatList(props.record? props.record : []);
    }, [props.record]);

    const sendMessage = (val, other_params_data = {}, chat) => {
        console.log('sendMessage', val, other_params_data, chat);
        if (!loading && props.applicationDetails?.name) {
            handleDebounceClick(val, other_params_data, chat);
        }
    };

    // const sendMessage = useCallback((val, other_params_data = {}, chat) => {
    //     console.log('sendMessage', val, other_params_data, chat);
    //     if (!loading && props.applicationDetails?.name) {
    //         handleDebounceClick(val, other_params_data, chat);
    //     }
    // }, [loading, props.applicationDetails]);

    const handleDebounceClick = debounce((val, other_params_data = {}, chat) => {
        chatMessage(chat, val, false, other_params_data);
    }, 200);

    const openChatId = async () => {
        const obj = props.applicationDetails;
        if (props.appId) {
            try {
                const res = await applicationApi.getChatOpen(props.appId);
                console.log(res, chartOpenId, '----res')
                console.log(chartOpenId, 'chartOpenId-----')
                return res.data;
            } catch (res) {
                if (res.response?.status === 403) {
                    await asyncAppAuthentication(accessToken);
                    return openChatId();
                }
                return Promise.reject(res);
            }
        } else {
            if (isWorkFlow(obj.type)) {
                const submitObj = {
                    work_flow: obj.work_flow
                };
                const res = await applicationApi.postWorkflowChatOpen(submitObj);
               
                return res.data;
            } else {
                const res = await applicationApi.postChatOpen(obj);
               
                return res.data;
            }
        }
    };

    // const getChartOpenId = async (chat?: any) => {
    //     // return .then(() => {
    //     //     chatMessage(chat);
    //     // });

    //     await openChatId();
    // }

    useEffect(() => {
        if(chartOpenId) {
            chatMessage(chat);
        }
    }, [chartOpenId])

    const getWrite = useCallback((chat, reader, stream) => {
        let tempResult = '';
        const write_stream = ({ done, value }) => {
            try {
                if (done) {
                    ChatManagement.close(chat.id);
                    return;
                }
                const decoder = new TextDecoder('utf-8');
                let str = decoder.decode(value, { stream: true });
                tempResult += str;
                const split = tempResult.match(/data:.*}\n\n/g);
                if (split) {
                    str = split.join('');
                    tempResult = tempResult.replace(str, '');
                } else {
                    return reader.read().then(write_stream);
                }
                if (str && str.startsWith('data:')) {
                    if (split) {
                        for (const index in split) {
                            const chunk = JSON.parse(split[index].replace('data:', ''));
                            chat.chat_id = chunk.chat_id;
                            chat.record_id = chunk.chat_record_id;
                            if (!chunk.is_end) {
                                ChatManagement.appendChunk(chat.id, chunk);
                            }
                            if (chunk.is_end) {
                                return Promise.resolve();
                            }
                        }
                    }
                }
            } catch (e) {
                return Promise.reject(e);
            }
            return reader.read().then(write_stream);
        };
        const write_json = ({ done, value }) => {
            if (done) {
                const result_block = JSON.parse(tempResult);
                if (result_block.code === 500) {
                    return Promise.reject(result_block.message);
                } else {
                    if (result_block.content) {
                        ChatManagement.append(chat.id, result_block.content);
                    }
                }
                ChatManagement.close(chat.id);
                return;
            }
            if (value) {
                const decoder = new TextDecoder('utf-8');
                tempResult += decoder.decode(value);
            }
            return reader.read().then(write_json);
        };
        return stream? write_stream : write_json;
    }, []);

    const errorWrite = (chat, message) => {
        ChatManagement.addChatRecord(chat, 50, loading);
        ChatManagement.write(chat.id);
        ChatManagement.append(chat.id, message || '抱歉，当前正在维护，无法提供服务，请稍后再试！');
        ChatManagement.updateStatus(chat.id, 500);
        ChatManagement.close(chat.id);
    };

    const chatMessage = async (chat, problem, re_chat = false, other_params_data = {}) => {
        setLoading(true);
        if (!chat) {
            chat = {
                id: randomId(),
                problem_text: problem? problem : inputValue.trim(),
                answer_text: '',
                answer_text_list: [{ content: '' }],
                buffer: [],
                write_ed: false,
                is_stop: false,
                record_id: '',
                chat_id: '',
                vote_status: '-1',
                status: undefined,
                upload_meta: {
                    image_list: other_params_data.image_list || [],
                    document_list: other_params_data.document_list || [],
                    audio_list: other_params_data.audio_list || []
                }
            };
            setChatList(prevChatList => [...prevChatList, chat]);
            ChatManagement.addChatRecord(chat, 50, loading);
            ChatManagement.write(chat.id);
            setInputValue('');
            await new Promise(resolve => setTimeout(resolve, 0));
            // if (scrollDiv.current) {
            //     scrollDiv.current.setScrollTop(getMaxHeight());
            // }
        }
        setChat(chat);
        
        if (chat.run_time) {
            ChatManagement.addChatRecord(chat, 50, loading);
            ChatManagement.write(chat.id);
        }
        if (!chartOpenId) {
            console.log(chartOpenId, 'chartOpenId----')
            try {
              const chatId = await openChatId()
              setChartOpenId(chatId);
            } catch (error) {
            errorWrite(chat);
            }
        } else {
            const obj = {
                message: chat.problem_text,
                re_chat: re_chat || false,
                ...other_params_data,
                form_data: {
                    ...form_data,
                    ...api_form_data
                }
            };
            try {
                const response = await applicationApi.postChatMessage(chartOpenId, obj);
                if (response.status === 401) {
                    await asyncAppAuthentication(accessToken);
                    chatMessage(chat, problem);
                } else if (response.status === 460) {
                    throw new Error('无法识别用户身份');
                } else if (response.status === 461) {
                    throw new Error('抱歉，您的提问已达到最大限制，请明天再来吧！');
                } else {
                    await new Promise(resolve => setTimeout(resolve, 0));
                    // if (scrollDiv.current) {
                    //     scrollDiv.current.setScrollTop(getMaxHeight());
                    // }
                    const reader = response.body.getReader();
                    const write = getWrite(
                        chat,
                        reader,
                        response.headers.get('Content-Type')!== 'application/json'
                    );
                    await reader.read().then(write);
                }
                if (props.chatId === 'new') {
                    props.onRefresh(chartOpenId);
                }
                if (id || props.applicationDetails?.show_source) {
                    await getSourceDetail(chat);
                }
            } catch (e) {
                errorWrite(chat, e + '');
            } finally {
                ChatManagement.close(chat.id);
            }
        }
    };

    const getSourceDetail = useCallback((row) => {
        return logApi.getRecordDetail(id || props.appId, row.chat_id, row.record_id, loading).then((res) => {
            const exclude_keys = ['answer_text', 'id', 'answer_text_list'];
            Object.keys(res.data).forEach((key) => {
                if (!exclude_keys.includes(key)) {
                    row[key] = res.data[key];
                }
            });
        });
    }, [id, props.appId, loading]);

    const [scrollTop, setScrollTop] = useState(0);
    const [scorll, setScorll] = useState(true);

    const getMaxHeight = useCallback(() => {
        return dialogScrollbar.current?.scrollHeight || 0;
    }, []);

    const handleScrollTop = useCallback((event) => {
        setScrollTop(event.scrollTop);
        if (
            dialogScrollbar.current &&
            scrollDiv.current &&
            dialogScrollbar.current.scrollHeight - (event.scrollTop + scrollDiv.current.wrapRef.offsetHeight) <= 30
        ) {
            setScorll(true);
        } else {
            setScorll(false);
        }
        props.onScroll({
           ...event,
            dialogScrollbar: dialogScrollbar.current,
            scrollDiv: scrollDiv.current
        });
    }, [props.onScroll]);

    // const handleScroll = useCallback(() => {
    //     if (props.type!== 'log' && scrollDiv.current && dialogScrollbar.current) {
    //         if (scrollDiv.current.wrapRef.offsetHeight < dialogScrollbar.current.scrollHeight) {
    //             if (scorll) {
    //                 scrollDiv.current.setScrollTop(getMaxHeight());
    //             }
    //         }
    //     }
    // }, [props.type, scrollDiv, dialogScrollbar, scorll, getMaxHeight]);

    useEffect(() => {
        window.sendMessage = sendMessage;
        return () => {
            window.sendMessage = null;
        };
    }, []);

    // useEffect(() => {
    //     handleScroll();
    // }, [chatList, handleScroll]);

    const setScrollBottom = useCallback(() => {
        if (scrollDiv.current) {
            scrollDiv.current.setScrollTop(getMaxHeight());
        }
    }, [scrollDiv, getMaxHeight]);

    useImperativeHandle(ref, () => ({
        setScrollBottom
    }));

    return (
        <div ref={aiChatRef} className={`ai-chat ${props.type === 'log'? 'chart-log' : ''}`}>
            <div ref={scrollDiv} >
                <div ref={dialogScrollbar} className="ai-chat__content p-24">
                    <PrologueContent
                        type={props.type}
                        application={props.applicationDetails}
                        available={props.available}
                        sendMessage={sendMessage}
                    />
                    {chatList.map((item, index) => (
                        <React.Fragment key={index}>
                            <QuestionContent application={props.applicationDetails} chatRecord={item} />
                            <AnswerContent
                                application={props.applicationDetails}
                                loading={loading}
                                chatRecord={item}
                                onUpdateChatRecord={(newChatRecord) => {
                                    setChatList(prevChatList => {
                                        const newList = [...prevChatList];
                                        newList[index] = newChatRecord;
                                        return newList;
                                    });
                                }}
                                type={props.type}
                                sendMessage={sendMessage}
                                chatManagement={ChatManagement}
                            />
                        </React.Fragment>
                    ))}
                </div>
            </div>
            {props.type!== 'log' && (
                            <ChatInputOperate
                                appId={props.appId}
                                applicationDetails={props.applicationDetails}
                                isMobile={isMobile}
                                type={props.type}
                                sendMessage={sendMessage}
                                chatManagement={ChatManagement}
                                chatId={chartOpenId}
                                // onUpdateChatId={(newChatId) => setChartOpenId(newChatId)}
                                loading={loading}
                                onUpdateLoading={(newLoading) => setLoading(newLoading)}
                            >
                                {props.children}
                            </ChatInputOperate>
                        )}
        </div>
    );
});

export default AiChat;